import { ComponentClass } from 'react'
import Taro, { Component, Config } from '@tarojs/taro'
import { View, Input, Text, Picker } from '@tarojs/components'
import { connect } from '@tarojs/redux'

import BankDetailHeader from '../../components/bank-detail-header'
import BankDetailBox from '../../components/bank-detail-box'
import BankApplyFlow from '../../components/bank-apply-flow'
import BankDetailDescBox from '../../components/bank-detail-desc-box'
import ProductFormButtonGroup from '../../components/product-form-button-group'

import './index.scss'

import { Utils } from '../../utils/utils';
import ProductUtils from '../../utils/product'
import { User as UserUtils } from '../../utils/user'
import { noConsole } from '../../config'
import Constants from '../../config/constants'

// const qqmapUtils = new QQmapUtils
const utils = new Utils()
const productUtils = new ProductUtils()
const userUtils = new UserUtils()

// #region 书写注意
// 
// 目前 typescript 版本还无法在装饰器模式下将 Props 注入到 Taro.Component 中的 props 属性
// 需要显示声明 connect 的参数类型并通过 interface 的方式指定 Taro.Component 子类的 props
// 这样才能完成类型检查和 IDE 的自动提示
// 使用函数模式则无此限制
// ref: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/20796
//
// #endregion

type PageStateProps = {
  product: any,   // 产品对象
  allTimeLimitOptions: number[],  // 产品的贷款期限数组
  userCollectionList: any[],    // 用户收藏产品列表
  userApplyList: any[],  // 用户申请列表
  form: {                // 表单对象
    deposit: number,
    time_limit: number,
  },
  redirectToUrl: string,
}

type PageDispatchProps = {
  dispatchSave: (param: any) => void,
  dispatchUpdateForm: (form: any) => void,
  dispatchGetBankProduct: (pid: string) => void,
  dispatchRefreshCollect: () => void,
  dispatchRefreshApply: () => void,
}

type PageOwnProps = {}

type PageState = {
  product_id: string,    // 产品id,
  eventRandomSuffix: string,    // 事件随机数后缀
}

type IProps = PageStateProps & PageDispatchProps & PageOwnProps

interface BankProductDetail {
  props: IProps;
  state: PageState;
}

@connect(({ bankProductDetial, common, loading }) => ({
  ...bankProductDetial,
  ...common,
  ...loading,
}), (dispatch) => ({
  dispatchSave(param: any) {
    dispatch({
      type: 'bankProductDetail/save',
      payload: param
    })
  },
  dispatchGetBankProduct(pid: string) {
    dispatch({
      type: 'bankProductDetial/getBankProductDetail',
      payload: {
        product_id: pid,
      }
    })
  },
  dispatchUpdateForm(form: any) {
    dispatch({
      type: 'bankProductDetial/updateForm',
      payload: {
        form,
      }
    })
  },
  dispatchRefreshCollect() {
    dispatch({
      type: 'common/refreshUserCollectionList',
      payload: {},
    })
  },
  dispatchRefreshApply() {
    dispatch({
      type: 'common/refreshUserApplyList',
      payload: {},
    })
  }
}))
class BankProductDetail extends Component {

  constructor(props) {
    super(props);

    this.state = {
      product_id: '',
      eventRandomSuffix: `_${utils.random(10)}`
    }
  }

  componentWillReceiveProps(nextProps) {

    // 显示加载中
    const productLoading = nextProps.effects['bankProductDetial/getBankProductDetail']
    // const collectLoading = nextProps.effects['common/refreshUserCollectionList']

    // 要发放在setTimeout里执行，否则小程序会报redux错误...  不知为啥
    if (productLoading) {
      setTimeout(() => {
        utils.showLoadingCenter()
      }, 0);
    }
    if (!productLoading) {
      setTimeout(() => {
        utils.hideLoadingCenter()
      }, 0);
    }
  }

  componentWillMount() {
    // 获取url中的 deposit 参数
    const { product_id } = this.$router.params
    this.setState({
      product_id,
    })

    // 检查是否已登录
    if (userUtils.isLoginValid()) {
      
      // 收藏列表为空，则更新
      if (this.props.userCollectionList.length === 0) {
        this.props.dispatchRefreshCollect()
      }

      // 申请列表为空，则更新
      if (this.props.userApplyList.length === 0) {
        this.props.dispatchRefreshApply()
      }
    } else {
      const url = `/pages/bankProductDetail/index?product_id=${product_id}`
      userUtils.checkIsLogin(url)
    }

  }

  componentDidMount() {
    if (userUtils.isLoginValid()) {
      // 加载产品详情数据
      this.props.dispatchGetBankProduct(this.state.product_id)
  
      // 监听申请
      this.initApplyEventWatch()
    }
  }

  componentWillUnmount() {
    // 取消监听
    this.removeApplyEventWatch()
  }

  componentDidShow() { }

  componentDidHide() { }

  render() {

    const { product, allTimeLimitOptions, form } = this.props

    return (
      <View className="bank-product-apply-container">
        {/* <!-- 头部信息分块 --> */}
        <View className="header">
          <View className="bank-product-apply-header">
            <BankDetailHeader product={product} />
          </View>
        </View>

        {/* <!-- 产品 detail 分块 --> */}
        <View className="detail-box">
          <View className="edit-box">
            <View className="item">
              <View className="top">
                <Text className="label">额度</Text>
                <View className="input">
                  <Input onBlur={this.onDepositBlur} type="number" value={productUtils.converToTenThousand(form.deposit) + ''} className="deposit-input" />
                  <Text className="suffix">万</Text>
                </View>
              </View>
              <View className="bottom">
                <Text className="detail">额度范围:{productUtils.convertDepositRangeToDisplayStr(product.min_deposit, product.max_deposit)}</Text>
              </View>
            </View>
            <View className="item">
              <View className="top">
                <Text className="label">期限</Text>
                <View className="input">
                  <Picker
                    mode={'selector'}
                    onChange={this.onTimeLimitPickerChange}
                    value={utils.getOptionIndex(form.time_limit, allTimeLimitOptions)}
                    range={allTimeLimitOptions}
                    className="selector">
                    <View className="content">
                      <View>
                        <Text className="text">
                          {form.time_limit}个月
                        </Text>
                      </View>
                      <View>
                        <Text className="iconfont icon-down-arrow"></Text>
                      </View>
                    </View>
                  </Picker>
                </View>
              </View>
              <View className="bottom">
                <Text className="detail">期限范围:{`${product.min_time_limit}-${product.max_time_limit}`}个月</Text>
              </View>
            </View>
          </View>

          {/* 产品详情table */}
          <View className="bank-detail-table-box">
            <BankDetailBox product={product} deposit={form.deposit} timeLimit={form.time_limit} />
          </View>

        </View>

        {/* 办理流程分块 */}
        <View className="flow-box">
          <BankApplyFlow />
        </View>

        {/* 申请条件分块 */}
        <View className="desc-box">
          <BankDetailDescBox title="申请条件" descText={product.apply_for_position} />
        </View>

        {/* 所需材料分块 */}
        <View className="desc-box-last">
          <BankDetailDescBox title="所需材料" descText={product.material_requested} />
        </View>

        {/* <!-- 提交申请分块 --> */}
        <View className="bottom-function-box">
          <ProductFormButtonGroup product={product}
            currentUrl={`/pages/bankProductDetail/index?product_id=${this.state.product_id}`}
            eventRandomSuffix={this.state.eventRandomSuffix} />
        </View>
      </View >
    )
  }

  /**
   * 额度blur监听
   * @param e
   */
  onDepositBlur = (e) => {
    // console.log('onDepositBlur, e = ', e)

    const { form, product } = this.props
    let deposit = e.detail.value * 10000 // 银行贷以万为单位，要乘10000
    form.deposit = deposit

    // 输入值校验
    deposit = productUtils.inputDepositeValidate(deposit, product)

    // 修改表单中的输入金额
    form.deposit = deposit

    this.props.dispatchUpdateForm({
      form,
    })
  }

  /**
   * 期限改变监听
   */
  onTimeLimitPickerChange = (e) => {
    // console.log('onTimeLimitPickerChange, e = ', e)

    const { form, allTimeLimitOptions } = this.props
    form.time_limit = parseFloat(utils.getOptionValueByIndex(e.detail.value, allTimeLimitOptions) + '')

    this.props.dispatchUpdateForm({
      form,
    })
  }

  /**
   * 产品申请处理方法
   */
  onApply() {
    // console.log('onApply!!')

    const url = this._getRedirectUrl(this.state.product_id, this.props.form.deposit, this.props.form.time_limit)
    if (userUtils.isLoginValid()) {
      Taro.navigateTo({
        url,
      })
    } else {
      userUtils.checkIsLogin(url)
    }
  }

  /**
   * 拼接跳转页面的url
   * @param deposit 额度
   * @param timeLimit 期限  
   */
  _getRedirectUrl(product_id: string, deposit: number, time_limit: number): string {
    const { redirectToUrl } = this.props
    return `${redirectToUrl}?product_id=${product_id}&deposit=${deposit}&time_limit=${time_limit}`
  }

  /**
   * 初始化申请事件监听
   */
  initApplyEventWatch() {
    Taro.eventCenter.on(`${Constants.FORM_GROUP_APPLY_EVENT}${this.state.eventRandomSuffix}`, () => {
      this.onApply()
    })
  }

  /**
   * 取消监听
   */
  removeApplyEventWatch() {
    Taro.eventCenter.off(`${Constants.FORM_GROUP_APPLY_EVENT}${this.state.eventRandomSuffix}`)
  }
}

// #region 导出注意
//
// 经过上面的声明后需要将导出的 Taro.Component 子类修改为子类本身的 props 属性
// 这样在使用这个子类时 Ts 才不会提示缺少 JSX 类型参数错误
//
// #endregion

export default BankProductDetail as ComponentClass<PageOwnProps, PageState>
